import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import nfa_generator.*;
import nfa_simulator.NFASimulator;
import DFA.*;
import ast_generator.*;



public class Scanner {
	public HashMap<String, ArrayList<String>> characterClasses;
	
	
	public static void main(String[] args) {
		
		
		/* Testing nfa methods */
		/*
		ArrayList<String> lowerCase = new ArrayList<String>(Arrays.asList("a", "b", "c", "d", "e", "f", "g" ,"h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"));
		ArrayList<String> upperCase = new ArrayList<String>(Arrays.asList("A", "B", "C", "D", "E", "F", "G" ,"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"));
		ArrayList<String> digit = new ArrayList<String>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0"));
		
		//$NAME: $UPPERCASE($LOWERCASE)+
		List<ASTTree> astList = new ArrayList<ASTTree>();
		ASTTree astTree = new ASTTree();
		astTree.setTokenType("$NAME");
		
		ASTNode root = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
		
		ASTNode temp = new ASTNode(upperCase, false);
		ASTNode temp2 = new ASTNode(new ArrayList<String>(Arrays.asList("+")), true);
				temp2.setLeft(new ASTNode(lowerCase, false));
		
		root.setLeft(temp);
		root.setRight(temp2);
		astTree.setRoot(root);
		astList.add(astTree);
		
		NFAGenerator nfaGen = new NFAGenerator(astList);
		NFAGraph nfaGraph = nfaGen.generateNFA();
		
		System.out.println("\n\n\nAST1 $NAME");
		for(NFANode node : nfaGraph.getStates()) {
			if(node.isAccepting()) {
				System.out.println("Accepting state");
			}
			System.out.println(node.toString());
		}
		
		
		//$VAR: ($UPPERCASE|$LOWERCASE)+($DIGIT|$LOWERCASE|$UPPERCASE)+
		List<ASTTree> astList2 = new ArrayList<ASTTree>();
		ASTTree astTree2 = new ASTTree();
		astTree2.setTokenType("$VAR");
		
		ASTNode root2 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
		
		ASTNode temp3 = new ASTNode(new ArrayList<String>(Arrays.asList("+")), true);
		ASTNode temp4 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
				temp4.setLeft(new ASTNode(upperCase, false));
				temp4.setRight(new ASTNode(lowerCase, false));
				temp3.setLeft(temp4);
		
		ASTNode temp5 = new ASTNode(new ArrayList<String>(Arrays.asList("+")), true);
		ASTNode temp6 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
		ASTNode temp7 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
				temp7.setLeft(new ASTNode(digit, false));
				temp7.setRight(new ASTNode(lowerCase, false));
				temp6.setLeft(temp7);
				temp6.setRight(new ASTNode(upperCase, false));
				temp5.setLeft(temp6);
				
		root2.setLeft(temp3);
		root2.setRight(temp5);
		astTree2.setRoot(root2);
		astList2.add(astTree2);
		
		NFAGenerator nfaGen2 = new NFAGenerator(astList2);
		NFAGraph nfaGraph2 = nfaGen2.generateNFA();
		
		System.out.println("\n\n\nAST2 $VAR");
		for(NFANode node : nfaGraph2.getStates()) {
			if(node.isAccepting()) {
				System.out.println("Accepting state");
			}
			System.out.println(node.toString());
		}
		
		
		//$EMAIL: ($UPPERCASE|$LOWERCASE|$DIGIT)+"@"($UPPERCASE|$LOWERCASE|$DIGIT)+"."$LOWERCASE$LOWERCASE$LOWERCASE
		List<ASTTree> astList3 = new ArrayList<ASTTree>();
		ASTTree astTree3 = new ASTTree();
		astTree3.setTokenType("$VAR");
		
		ASTNode root3 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
		
		//Sub root3
		ASTNode temp8 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
		ASTNode temp9 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				root3.setLeft(temp8);
				root3.setRight(temp9);
		
		//Sub temp8
		ASTNode temp10 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);				
		ASTNode temp11 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				temp8.setLeft(temp10);
				temp8.setRight(temp11);
		
		//Sub temp9
		ASTNode temp12 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
		ASTNode temp13 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				temp9.setLeft(temp12);
				temp9.setRight(temp13);
		
		//Sub temp10
		ASTNode temp14 = new ASTNode(new ArrayList<String>(Arrays.asList("+")), true);
		ASTNode temp15 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
		ASTNode temp16 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
				temp16.setLeft(new ASTNode(upperCase, false));
				temp16.setRight(new ASTNode(lowerCase, false));		
				temp15.setLeft(temp16);
				temp15.setRight(new ASTNode(digit, false));
				temp14.setLeft(temp15);
				temp10.setLeft(temp14);
				temp10.setRight(new ASTNode(new ArrayList<String>(Arrays.asList("@")), false));
				
		//Sub temp11	
		ASTNode temp17 = new ASTNode(new ArrayList<String>(Arrays.asList("+")), true);
		ASTNode temp18 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
		ASTNode temp19 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
				temp19.setLeft(new ASTNode(upperCase, false));
				temp19.setRight(new ASTNode(lowerCase, false));		
				temp18.setLeft(temp19);
				temp18.setRight(new ASTNode(digit, false));
				temp17.setLeft(temp18);
				temp11.setLeft(temp17);
				temp11.setRight(new ASTNode(new ArrayList<String>(Arrays.asList(".")), false));
				
		//Sub temp12
		temp12.setLeft(new ASTNode(lowerCase, false));
		temp12.setRight(new ASTNode(lowerCase, false));
		
		//Sub temp13
		temp13.setLeft(new ASTNode(lowerCase, false));

		
		astTree3.setRoot(root3);
		astList3.add(astTree3);
		
		NFAGenerator nfaGen3 = new NFAGenerator(astList3);
		NFAGraph nfaGraph3 = nfaGen3.generateNFA();
		
		System.out.println("\n\n\nAST3 $EMAIL");
		for(NFANode node : nfaGraph3.getStates()) {
			if(node.isAccepting()) {
				System.out.println("Accepting state");
			}
			System.out.println(node.toString());
		}
		
		//Testing null values
		//lowerCase*|upperCase
		List<ASTTree> astList4 = new ArrayList<ASTTree>();
		ASTTree astTree4 = new ASTTree();
		astTree4.setTokenType("$SOMETHING");
		
		ASTNode root4 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
		ASTNode temp20 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
				root4.setLeft(temp20);
				root4.setRight(new ASTNode(null, false));
				
		ASTNode temp21 = new ASTNode(new ArrayList<String>(Arrays.asList("|")), true);
		ASTNode temp22 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				temp20.setLeft(temp21);
				temp20.setRight(temp22);
				temp22.setLeft(new ASTNode(null, false));
				temp22.setRight(new ASTNode(null, false));		
		
		ASTNode temp23 = new ASTNode(new ArrayList<String>(Arrays.asList("*")), true);
		ASTNode temp24 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				temp21.setLeft(temp23);
				temp21.setRight(temp24);
				temp24.setLeft(new ASTNode(null, false));
				temp24.setRight(new ASTNode(upperCase, false));
		
		ASTNode temp25 = new ASTNode(new ArrayList<String>(Arrays.asList("concat")), true);
				temp23.setLeft(temp25);
				temp25.setLeft(new ASTNode(lowerCase, false));
				temp25.setRight(new ASTNode(null, false));
		
		
		astTree4.setRoot(root4);
		astList4.add(astTree4);
		
		NFAGenerator nfaGen4 = new NFAGenerator(astList4);
		NFAGraph nfaGraph4 = nfaGen4.generateNFA();
		
		System.out.println("\n\n\nAST4 $SOMETHING");
		for(NFANode node : nfaGraph4.getStates()) {
			if(node.isAccepting()) {
				System.out.println("Accepting state");
			}
			System.out.println(node.toString());
		}
		*/
		/*
		NFASimulator simulator = new NFASimulator(nfaGraph, "hello");
		simulator.simulate();
		System.out.println(simulator.getToken());
		System.out.println(simulator.getTokenType());		
		*/
	}
}
